package edu.westga.sketchit2009cs.gui;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import edu.westga.sketchit2009cs.controller.Sketchit2009csApplication;
import edu.westga.sketchit2009cs.network.*;
import edu.westga.sketchit2009cs.stringBufferServer.DrawingServer;
/**
 * HostPanel defines the framework of the GUI for hosting a new Sketchit2009cs
 * game. Its content pane will be allow host to insert their name, port number,
 * their IP address, and the number of players for that game. This Panel also
 * defines their computer as the server for the game.
 * 
 * @author Steven Campbell, RJ Hill, Daniel Reeves, Fall 2009
 * 
 */
public class HostPanel extends JPanel {
	/**
	 * The Join Panel Lets clients join SketchIt 2009 hosted servers.
	 */

	private static final long serialVersionUID = 1L;
	private JPanel hostComponents;
	private JLabel playerNameLabel;
	private JFormattedTextField playerTextField;
	public JFormattedTextField portTextField;
	private JFormattedTextField numberOfPlayersTextField;
	private JPanel buttonPanel;
	private JLabel portLabel;
	private JLabel addNumberOfPlayersLabel;
	public final String PERIOD_STRING_VALUE = ".";
	public final String HOST_WELCOME_STRING_VALUE = "Please insert the Required information to Host a game.";
	public final String HOST_NAME_STRING_VALUE = "Host Name";
	public final String IP_ADDRESS_STRING_VALUE = "IP address";
	public final String HOST_IP_ADDRESS_STRING_VALUE = "The IP Address of this machine is: ";
	public final String DEFAULT_PORT_NUMBER_STRING_VALUE = "5000";
	public final String FORWARD_SLASH_STRING_VALUE = "/";
	public final String PORT_NUMBER_STRING_VALUE = "Port Number";
	public final String NUMBER_OF_PLAYERS_STRING_VALUE = "Number of Players";
	public final String OK_BUTTON_STRING_VALUE = "    OK    ";
	public final String CANCEL_BUTTON_STRING_VALUE = "Cancel";
	public final String CLEAR_FORM_BUTTON_STRING_VALUE = "Clear Form";
	public final String NULL_STRING_VALUE = "";
	public final String HOST_NAME_REQUIREMENTS_STRING_VALUE = "Your name can only be 3 - 20 characters.";
	public final String HOST_NAME_ERROR_TITLE_NAME_VALUE = "Error. Incorrect Data in Host Name";
	public final String IP_ADDRESS_REQUIREMENTS_STRING_VALUE = "Each IP address textbox can must be a value between 0 and 255.";
	public final String IP_ADDRESS_ERROR_TITLE_STRING_VALUE = "Error. Incorrect Data in IP address";
	public final String IP_ADDRESS_EXCEPTION_MESSAGE = "The IP address can only have numbers in it, and cannot be blank.";
	public final String PORT_NUMBER_REQUIREMENTS_STRING_VALUE = "The port can only be between 1024 and 65535.";
	public final String PORT_NUMBER_ERROR_TITLE_STRING_VALUE = "Error. Incorrect Data in Port number.";
	public final String PORT_NUMBER_EXCEPTION_MESSAGE = "The port can only have numbers in it ,cannot be blank, and cannot be a huge number.";
	public final String NUMBER_OF_PLAYERS_REQUIREMENTS_STRING_VALUE = "You can only have 2 to 10 players in your game.";
	public final String NUMBER_OF_PLAYERS_ERROR_TITLE_STRING_VALUE = "Error. Incorrect Data in number of players";
	public final String NUMBER_OF_PLAYERS_EXCEPTION_MESSAGE = "The number of players can only have numbers in it and cannot be blank.";

	/**
	 * The Constructor for the HostPanel
	 * 
	 * @throws Exception
	 *             trying to find the host's IP address may throw an Exception.
	 */
	public HostPanel() throws Exception {
		super();

		this.build();
	}

	// Creates the HostPanel on the current GUI.
	public void build() throws Exception {
		hostComponents = new JPanel();
		this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
		this.setAlignmentX(Component.CENTER_ALIGNMENT);

		setUpUserInformation();
		this.setBackground(Color.LIGHT_GRAY);
	}

	// adds the welcome Message on the HostPanel.
	private void addWelcomeMessage() throws Exception {

		JPanel welcomeMessagePanel = new JPanel();
		welcomeMessagePanel.setLayout(new BoxLayout(welcomeMessagePanel,
				BoxLayout.X_AXIS));
		welcomeMessagePanel.setAlignmentX(Component.CENTER_ALIGNMENT);
		JLabel welcomeMessageLabel = new JLabel(HOST_WELCOME_STRING_VALUE);
		welcomeMessagePanel.setBackground(Color.LIGHT_GRAY);
		welcomeMessagePanel.add(welcomeMessageLabel);

		this.hostComponents.add(welcomeMessagePanel);
	}

	// Sets up the Host Required information to Host a game.
	private void setUpUserInformation() throws Exception {

		this.hostComponents = new JPanel();
		this.hostComponents.setLayout(new BoxLayout(this.hostComponents,
				BoxLayout.Y_AXIS));
		this.hostComponents.setAlignmentY(Component.CENTER_ALIGNMENT);
		this.hostComponents.setBackground(Color.LIGHT_GRAY);
		this.hostComponents.add(Box.createRigidArea(new Dimension(5, 75)));
		addWelcomeMessage();
		this.hostComponents.add(Box.createRigidArea(new Dimension(5, 25)));
		addPlayerName();
		this.hostComponents.add(Box.createRigidArea(new Dimension(5, 25)));
		addHostIp();
		this.hostComponents.add(Box.createRigidArea(new Dimension(5, 25)));
		addPortNumber();
		this.hostComponents.add(Box.createRigidArea(new Dimension(5, 25)));
		addNumberOfPlayers();
		this.hostComponents.add(Box.createRigidArea(new Dimension(5, 25)));
		setButtonDisplayPanel();
		this.hostComponents.add(Box.createRigidArea(new Dimension(5, 250)));

		this.add(this.hostComponents);

	}

	// Adds Host name components
	private void addPlayerName() throws Exception {
		JPanel addPlayerPanel = new JPanel();
		addPlayerPanel
				.setLayout(new BoxLayout(addPlayerPanel, BoxLayout.X_AXIS));
		addPlayerPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
		this.playerNameLabel = new JLabel();
		addPlayerPanel.add(Box.createRigidArea(new Dimension(50, 5)));
		this.playerNameLabel.setText(HOST_NAME_STRING_VALUE);
		this.playerNameLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
		addPlayerPanel.setBackground(Color.LIGHT_GRAY);
		this.playerTextField = new JFormattedTextField();
		this.playerTextField.setMaximumSize(new Dimension (225,20));
		addPlayerPanel.add(this.playerNameLabel);
		addPlayerPanel.add(Box.createRigidArea(new Dimension(65, 5)));
		addPlayerPanel.add(this.playerTextField);
		addPlayerPanel.add(Box.createRigidArea(new Dimension(155, 5)));
		this.hostComponents.add(addPlayerPanel);

	}

	// Add the host's IP address to the hostComponents panel.
	private void addHostIp() throws Exception {
		JPanel addIPHostAddressPanel = new JPanel();
		addIPHostAddressPanel.setBackground(Color.LIGHT_GRAY);
		addIPHostAddressPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
		addIPHostAddressPanel.setLayout(new BoxLayout(addIPHostAddressPanel,
				BoxLayout.X_AXIS));
		String[] iPAddress = getHostIpAddress();
		JLabel hostIP = new JLabel(iPAddress[1]);
		JLabel addIPHostAddressLabel = new JLabel(HOST_IP_ADDRESS_STRING_VALUE);
		
		addIPHostAddressPanel.add(addIPHostAddressLabel);
		addIPHostAddressPanel.add(Box.createRigidArea(new Dimension(37, 0)));
		addIPHostAddressPanel.add(hostIP);
		this.hostComponents.add(addIPHostAddressPanel);
		addIPHostAddressPanel.add(Box.createRigidArea(new Dimension(140, 5)));
	}

	//Get the host IP address
	public String[] getHostIpAddress() throws UnknownHostException {
		InetAddress Address = InetAddress.getLocalHost();
		String[] iPAddress = Address.toString().split(
				FORWARD_SLASH_STRING_VALUE);
		return iPAddress;
	}

	// Adds Port number components
	private void addPortNumber() throws Exception {
		JPanel addPortPanel = new JPanel();
		addPortPanel.setLayout(new BoxLayout(addPortPanel, BoxLayout.X_AXIS));
		addPortPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
		this.portLabel = new JLabel();
		addPortPanel.add(Box.createRigidArea(new Dimension(50, 5)));
		this.portLabel.setText(PORT_NUMBER_STRING_VALUE);
		this.portLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
		addPortPanel.setBackground(Color.LIGHT_GRAY);
		this.portTextField = new JFormattedTextField();
		this.portTextField.setMaximumSize(new Dimension (70,20));
		addPortPanel.add(this.portLabel);
		this.portTextField.setText(DEFAULT_PORT_NUMBER_STRING_VALUE);
		addPortPanel.add(Box.createRigidArea(new Dimension(150, 5)));
		addPortPanel.add(this.portTextField);
		addPortPanel.add(Box.createRigidArea(new Dimension(50, 5)));
		this.hostComponents.add(addPortPanel);
		addPortPanel.add(Box.createRigidArea(new Dimension(165, 5)));

	}

	// Adds the number of players components
	private void addNumberOfPlayers() throws Exception {
		JPanel addNumberOfPlayersPanel = new JPanel();
		addNumberOfPlayersPanel.setLayout(new BoxLayout(
				addNumberOfPlayersPanel, BoxLayout.X_AXIS));
		addNumberOfPlayersPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
		this.addNumberOfPlayersLabel = new JLabel();
		addNumberOfPlayersPanel.add(Box.createRigidArea(new Dimension(50, 5)));
		this.addNumberOfPlayersLabel.setText(NUMBER_OF_PLAYERS_STRING_VALUE);
		this.addNumberOfPlayersLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
		addNumberOfPlayersPanel.setBackground(Color.LIGHT_GRAY);
		this.numberOfPlayersTextField = new JFormattedTextField();
		this.numberOfPlayersTextField.setMaximumSize(new Dimension(40,20));
		this.numberOfPlayersTextField.setMinimumSize(new Dimension(40,20));
		addNumberOfPlayersPanel.add(this.addNumberOfPlayersLabel);
		addNumberOfPlayersPanel.add(Box.createRigidArea(new Dimension(130, 5)));
		addNumberOfPlayersPanel.add(this.numberOfPlayersTextField);
		addNumberOfPlayersPanel.add(Box.createRigidArea(new Dimension(70, 5)));
		this.hostComponents.add(addNumberOfPlayersPanel);
		addNumberOfPlayersPanel.add(Box.createRigidArea(new Dimension(165, 5)));

	}

	// Sets up the OK and Cancel buttons
	private void setButtonDisplayPanel() throws Exception {
		this.buttonPanel = new JPanel();
		this.buttonPanel.setLayout(new BoxLayout(this.buttonPanel,
				BoxLayout.X_AXIS));
		this.buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
		this.buttonPanel.setBackground(Color.LIGHT_GRAY);
		JButton okButton = new JButton(OK_BUTTON_STRING_VALUE);
		okButton.addActionListener(new OkButtonListener());
		JButton cancelButton = new JButton(CANCEL_BUTTON_STRING_VALUE);
		cancelButton
				.addActionListener(new Sketchit2009csMainFrame.CancelButtonListener());
		JButton clearAllButton = new JButton(CLEAR_FORM_BUTTON_STRING_VALUE);
		clearAllButton.setAlignmentX(RIGHT_ALIGNMENT);
		clearAllButton.addActionListener(new ClearAllButtonListener());
		this.buttonPanel.add(Box.createRigidArea(new Dimension(110, 5)));
		this.buttonPanel.add(okButton);
		this.buttonPanel.add(Box.createRigidArea(new Dimension(65, 5)));
		this.buttonPanel.add(cancelButton);
		this.buttonPanel.add(Box.createRigidArea(new Dimension(50, 5)));
		this.buttonPanel.add(clearAllButton);
		this.buttonPanel.add(Box.createRigidArea(new Dimension(50, 5)));

		this.hostComponents.add(buttonPanel);
	}

	// Action listener that lets you cancel Host Game.
	private class ClearAllButtonListener implements ActionListener {

		/*
		 * Clears out the Text Field panels.
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			portTextField.setText(NULL_STRING_VALUE);
			numberOfPlayersTextField.setText(NULL_STRING_VALUE);
		}
	}

	// Action listener that lets you Host a Game.
	private class OkButtonListener implements ActionListener {

		/*
		 * Loads the Game interface panel.
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			boolean correctInfo = checkHostInformation();
			
			if (correctInfo == true) {
				
				Sketchit2009csMainFrame.playerName = playerTextField.getText();
				Sketchit2009csMainFrame.hostAndJoinPortNumber = Integer.parseInt(portTextField.getText());
				hostComponents.removeAll();
				try {
					Sketchit2009csApplication.threadManager.execute(new
							ChatServer(Sketchit2009csMainFrame.hostAndJoinPortNumber));
					Sketchit2009csApplication.threadManager.execute(new DrawingServer());
				} catch (Exception e1) {
					e1.printStackTrace();
				}
				hostComponents.add(new GameInterface(Sketchit2009csMainFrame.hostIpAddress));
				hostComponents.validate();
				hostComponents.repaint();
			}
		}
	}

	// Method that checks to see if host information inserted is correct.
	private boolean checkHostInformation() {

		// Test the host name
		if (this.playerTextField.getText().length() > 20
				|| this.playerTextField.getText().length() < 3) {
			JDialog errorDialog = new JDialog();
			JOptionPane.showMessageDialog(errorDialog,
					HOST_NAME_REQUIREMENTS_STRING_VALUE,
					HOST_NAME_ERROR_TITLE_NAME_VALUE, 0);
			return false;
		}
		
		// Test the port number of the host.
		try {
			int theParsed = Integer.parseInt(this.portTextField.getText()
					.trim());
			if (theParsed < 1024 || theParsed > 65535) {
				JDialog errorDialog = new JDialog();
				JOptionPane.showMessageDialog(errorDialog,
						PORT_NUMBER_REQUIREMENTS_STRING_VALUE,
						PORT_NUMBER_ERROR_TITLE_STRING_VALUE, 0);
				return false;
			}

		} catch (NumberFormatException e) {
			JDialog errorDialog = new JDialog();
			JOptionPane.showMessageDialog(errorDialog,
					PORT_NUMBER_EXCEPTION_MESSAGE,
					PORT_NUMBER_ERROR_TITLE_STRING_VALUE, 0);
			return false;
		}

		// Test the number of players inserted.
		try {
			int theParsed = Integer.parseInt(this.numberOfPlayersTextField
					.getText().trim());

			if (theParsed < 2 || theParsed > 10) {
				JDialog errorDialog = new JDialog();
				JOptionPane.showMessageDialog(errorDialog,
						NUMBER_OF_PLAYERS_REQUIREMENTS_STRING_VALUE,
						NUMBER_OF_PLAYERS_ERROR_TITLE_STRING_VALUE, 0);
				return false;
			}

		} catch (NumberFormatException e) {
			JDialog errorDialog = new JDialog();
			JOptionPane.showMessageDialog(errorDialog,
					NUMBER_OF_PLAYERS_EXCEPTION_MESSAGE,
					NUMBER_OF_PLAYERS_ERROR_TITLE_STRING_VALUE, 0);
			return false;
		}

		return true;
	}

}
